/*
 Copyright (C) 2010-2013. 
 Ezequiel Palumbo, Calipsoide FOSS Foundation.
 
 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU Lesser General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU Lesser General Public License for more details.

 You should have received a copy of the GNU Lesser General Public License
 along with this program.  If not, see http://www.gnu.org/licenses/. 
 
 Email: contacto@ehpalumbo.com.ar 
*/

package org.calipsoide.dbf2xml.xml;

import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;

import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;

/**
 * 
 * Transformer for a DOM object. It is an utility class. 
 * Writes document with a standard format directly over an OutputStream.  
 * 
 * @since 1.0
 * @author ehpalumbo
 *
 */
public class XMLWriter {

	public static final String DEFAULT_ENCODING = "utf-8";
	public static final int DEFAULT_INDENT = 4;
	
	private String encoding;
	private Integer indentNumber;
	
	/**
	 * 
	 * Default constructor.
	 * 
	 */
	public XMLWriter() {
		this(null, null);
	}
	
	/**
	 * 
	 * Creates writer with specified encoding, and default indentation.
	 * 
	 * @param encoding of the output
	 * 
	 */
	public XMLWriter(String encoding) {
		this(encoding, null);
	}

	/**
	 * 
	 * Creates writer with specified indentation, and default encoding.
	 * 
	 * @param indent number of spaces used for indentation
	 * 
	 */
	public XMLWriter(Integer indent) {
		this(null, indent);
	}

	/**
	 * 
	 * Creates writer with specified encoding indentation. 
	 * In case of null parameters it uses defaults. 
	 * 
	 * @param encoding of the output
	 * @param indent number of spaces used for indentation
	 * 
	 */
	public XMLWriter(String encoding, Integer indent) {
		super();
		this.encoding = (encoding == null ? DEFAULT_ENCODING : encoding);
		this.indentNumber = (indent == null ? DEFAULT_INDENT : indent);
	}

	public String getEncoding() {
		return encoding;
	}
	
	public Integer getIndentNumber() {
		return indentNumber;
	}

	public boolean isIndentRequired() {
		return getIndentNumber() != null;
	}
	
	/**
	 * 
	 * Writes the Document over the OutputStream, with the defined settings.
	 * 
	 * @param source document with data
	 * @param outputStream on which writing is done
	 * @throws IOException if anything goes wrong when writing
	 * 
	 */
	public void write(
			final Document source, 
			final OutputStream outputStream)
			throws IOException {
		try {
			final TransformerFactory transformerFactory = 
					TransformerFactory.newInstance();
			if (isIndentRequired()) {
				transformerFactory.setAttribute(
						"indent-number", getIndentNumber());
			}
			final Transformer transformer = 
					transformerFactory.newTransformer();
			if (isIndentRequired()) {
				transformer.setOutputProperty(OutputKeys.INDENT, "yes");
			}
			final DOMSource domSource = new DOMSource(source);
			final StreamResult result = new StreamResult(
					new OutputStreamWriter(outputStream, getEncoding()));
			transformer.transform(domSource, result);
		} catch (TransformerException e) {
			throw new IOException("Error trying to transform source.", e);
		}
	}

}
